package com.xiaozhu.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis 配置类
 *
 * 作用：
 * 1. 配置 RedisTemplate，使 key/value 使用 JSON 序列化
 * 2. 配置 Spring Cache（注解缓存，如 @Cacheable）使用 Redis 并用 JSON 序列化
 */
@Configuration
@EnableCaching // 开启 Spring Cache 注解支持（如 @Cacheable、@CachePut、@CacheEvict）
public class RedisConfig {

    /**
     * 自定义 RedisTemplate Bean
     *
     * @param factory Redis 连接工厂，由 Spring 注入
     * @return RedisTemplate 对象，可直接注入使用
     *
     * 核心作用：
     * - key 用 String 序列化（便于直接用字符串作为缓存 key）
     * - value 用 JSON 序列化（支持存储任意对象，不需要实现 Serializable）
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 设置 Redis 连接工厂
        template.setConnectionFactory(factory);

        // --------------------- key 序列化 ---------------------
        // Redis 的 key 使用字符串序列化，方便查看和管理
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer()); // Hash 类型 key 也用字符串

        // --------------------- value 序列化 ---------------------
        // Redis 的 value 使用 JSON 序列化器
        // 优点：可读性高，存储对象无需实现 Serializable
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(serializer);      // 普通 key/value
        template.setHashValueSerializer(serializer);  // Hash 类型 value

        // 完成属性设置后初始化
        template.afterPropertiesSet();

        return template;
    }

    /**
     * 配置 Spring Cache 使用 Redis
     *
     * @param factory Redis 连接工厂
     * @return RedisCacheManager，用于 Spring Cache 注解
     *
     * 核心作用：
     * - 缓存存储在 Redis
     * - value 使用 JSON 序列化
     * - 设置默认缓存过期时间（TTL）
     */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        // 配置默认序列化器和过期时间
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 序列化 value 为 JSON
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
                        new GenericJackson2JsonRedisSerializer()
                ))
                // 设置缓存过期时间，单位：秒/分钟/小时
                .entryTtl(Duration.ofHours(1)); // 这里设置 1 小时，可根据业务调整

        // 创建并返回 RedisCacheManager
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config) // 设置默认配置
                .build();
    }
}
